package com.sen.paydemo.config;

import com.wechat.pay.contrib.apache.httpclient.Validator;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.*;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import lombok.Data;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;

/**
 * 微信支付相关配置
 */
// @Configuration
// @PropertySource("classpath:wxpay.properties") //这个注解 读取的是 properties 配置文件
@Component
@ConfigurationProperties(prefix = "wxpay") // 读取wxpay节点
@Data
public class WxPayConfig {

    /**
     * 商户号
     */
    private String mchId;

    /**
     * 商户API证书序列号
     */
    private String mchSerialNo;

    /**
     * 商户私钥文件 路径
     */
    private String privateKeyPath;

    /**
     * APIv3密钥
     */
    private String apiV3Key;

    /**
     * APPID
     */
    private String appid;

    /**
     * 微信服务器地址
     */
    private String domain;

    /**
     * 接收结果通知地址
     */
    private String notifyDomain;


    /**
     * 获取商户私钥文件
     *
     * @return
     */
    private PrivateKey getPrivateKey(String fileName) {
        // 拼接 路径
        fileName = System.getProperty("user.dir") + fileName;
        System.out.println("getPrivateKey私钥文件地址: " + fileName);
        try {
            PrivateKey privateKey = PemUtil.loadPrivateKey(
                    new FileInputStream(fileName));
            return privateKey;
        } catch (FileNotFoundException e) {
            throw new RuntimeException("私钥文件不存在...", e);
        }
    }

    /**
     * 自动更新微信支付平台证书
     * 初始化config对象，这个对象在构建各种支付执行器对象的时候需要传入，并且可复用
     * 代码地址: https://github.com/wechatpay-apiv3/wechatpay-java
     * @return
     */
    //@Bean
    public Config getConfig() {

        //System.out.println("getConfig私钥文件地址: " +  privateKeyPath);
        Config config =
                new RSAAutoCertificateConfig.Builder()
                        .merchantId(mchId)
                        .privateKeyFromPath(System.getProperty("user.dir") + privateKeyPath)
                        .merchantSerialNumber(mchSerialNo)
                        .apiV3Key(apiV3Key)
                        .build();
        return config;
    }

    /**
     * 不是推荐的
     * 定时更新平台证书功能
     * 代码地址: https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient
     * @return
     * @throws Exception
     */
    // @Bean
    public CloseableHttpClient getHttpClient() throws Exception {
        // 获取证书管理器实例
        CertificatesManager certificatesManager = CertificatesManager.getInstance();
        // 向证书管理器增加需要自动更新平台证书的商户信息
        certificatesManager.putMerchant(mchId, new WechatPay2Credentials(mchId,
                new PrivateKeySigner(mchSerialNo, getPrivateKey(privateKeyPath))), apiV3Key.getBytes(StandardCharsets.UTF_8));

        // ... 若有多个商户号，可继续调用putMerchant添加商户信息
        // 从证书管理器中获取verifier
        Verifier verifier = certificatesManager.getVerifier(mchId);
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(mchId, mchSerialNo, getPrivateKey(privateKeyPath))
                .withValidator((Validator) verifier);

        // ... 接下来，你仍然可以通过builder设置各种参数，来配置你的HttpClient
        // 通过WechatPayHttpClientBuilder构造的HttpClient，会自动的处理签名和验签，并进行证书自动更新
        CloseableHttpClient httpClient = builder.build();


        return httpClient;
    }

    /**
     * 官方推荐这个
     * 通用 支付 的验签
     * 创建加载商户私钥、加载平台证书、初始化httpClient的通用方法。
     * @return
     * @throws Exception
     */
    // @Bean
    public CloseableHttpClient getCloseableHttpClient() throws Exception {
        // 加载商户私钥（privateKey：私钥字符串）
        PrivateKey merchantPrivateKey = PemUtil
                .loadPrivateKey(new ByteArrayInputStream((System.getProperty("user.dir") + privateKeyPath).getBytes("utf-8")));

        // 加载平台证书（mchId：商户号,mchSerialNo：商户证书序列号,apiV3Key：V3密钥）
        AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
                new WechatPay2Credentials(mchId, new PrivateKeySigner(mchSerialNo, merchantPrivateKey)), apiV3Key.getBytes("utf-8"));

        // 初始化httpClient
        CloseableHttpClient closeableHttpClient = WechatPayHttpClientBuilder.create()
                .withMerchant(mchId, mchSerialNo, merchantPrivateKey)
                .withValidator(new WechatPay2Validator(verifier)).build();
        return closeableHttpClient;
    }


}
